package spu

import (
	"context"
	"fmt"
	"mall/common/excption"
	tools "mall/common/utils"
	constans "mall/services/product/rpc/consts"
	"mall/services/product/rpc/internal/domain/bo"
	"mall/services/product/rpc/internal/domain/do"
	"mall/services/product/rpc/internal/mapper"
	"mall/services/product/rpc/internal/mapper/entity"
	"mall/services/product/rpc/internal/svc"
	"mall/services/product/rpc/pb"

	"github.com/zeromicro/go-zero/core/logx"
)

type QuerySpuInfoLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewQuerySpuInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QuerySpuInfoLogic {
	return &QuerySpuInfoLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *QuerySpuInfoLogic) QuerySpuInfo(in *pb.QuerySpuInfoDTO) (*pb.QuerySpuInfoVO, error) {
	// 1.query spu info
	spuBO := bo.SpuBO{SpuId: in.SpuId}
	spuMapper := mapper.NewSpuMapper[entity.SpuEntity]()
	spuEntity, err := spuMapper.SelectOneCtx(l.ctx, l.svcCtx.DBEngin, spuBO)
	if err != nil {
		return nil, err
	}
	if spuEntity.SpuId <= 0 {
		return nil, excption.NewErrCode(constans.SpuInfoNoExistError)
	}
	// 2.query spu att
	attrValueVoArr, err2 := l.querySpuAttr(in, err)
	if err2 != nil {
		return nil, err2
	}
	// 4.query skuAttr
	spuSkuAttrValueMap, err3 := l.querySkuAttr(in, err)
	if err3 != nil {
		return nil, err3
	}
	// 4.query skuList
	skuMapper := mapper.NewSkuMapper()
	selectListCtx, err := skuMapper.SelectSkuListBySpuId(l.ctx, l.svcCtx.DBEngin, in.SpuId)
	if err != nil {
		return nil, err
	}
	// 5.return obj
	resp := l.returnObj(spuEntity, selectListCtx, spuSkuAttrValueMap, attrValueVoArr)
	return resp, nil
}

func (l *QuerySpuInfoLogic) returnObj(spuEntity entity.SpuEntity, selectListCtx []do.SkuInfoDO,
	spuSkuAttrValueMap map[int64][]entity.SpuSkuAttrValueEntity, attrValueVoArr []*pb.SpuAttrValueVO) *pb.QuerySpuInfoVO {
	// spu info
	resp := new(pb.QuerySpuInfoVO)
	resp.SpuId = spuEntity.SpuId
	resp.CreateTime = spuEntity.CreateTime.Format("2006-01-02 15:04:05")
	resp.UpdateTime = spuEntity.UpdateTime.Format("2006-01-02 15:04:05")
	resp.BrandId = spuEntity.BrandId
	resp.BrandName = spuEntity.BrandName
	resp.CategoryId = spuEntity.CategoryId
	resp.CategoryName = spuEntity.CategoryName
	resp.ShopCategoryId = spuEntity.ShopCategoryId
	resp.ShopCategoryName = spuEntity.ShopCategoryName
	resp.ShopId = spuEntity.ShopId
	resp.ShopName = spuEntity.ShopName
	resp.Name = spuEntity.Name
	resp.SellingPoint = spuEntity.SellingPoint
	resp.MainImgUrl = spuEntity.MainImgUrl
	resp.ImgUrls = spuEntity.ImgUrls
	resp.PriceFee = spuEntity.PriceFee
	resp.MarketPriceFee = spuEntity.MarketPriceFee
	resp.Status = int32(spuEntity.Status)
	resp.HasSkuImg = int32(spuEntity.HasSkuImg)
	resp.Seq = int32(spuEntity.Seq)
	var spuStock int32
	var spuActualStock int32
	// sku info
	var skuInfoArr []*pb.SkuInfoVO
	if len(selectListCtx) > 0 {
		for _, v := range selectListCtx {
			vo := pb.SkuInfoVO{}
			vo.SkuId = v.SkuId
			vo.SkuName = v.SkuName
			vo.Attrs = v.Attrs
			vo.ImgUrl = v.ImgUrl
			vo.PriceFee = v.PriceFee
			vo.MarketPriceFee = v.MarketPriceFee
			vo.PartyCode = v.PartyCode
			vo.ModelId = v.ModelId
			vo.Weight = float32(v.Weight)
			vo.Volume = float32(v.Volume)
			vo.Status = int32(v.Status)
			spuSkuAttrValueArr := spuSkuAttrValueMap[v.SkuId]
			// sku attr
			var spuSkuAttrArr []*pb.SpuSkuAttrValueVO
			if len(spuSkuAttrValueArr) > 0 {
				for _, v := range spuSkuAttrValueArr {
					skuAttr := new(pb.SpuSkuAttrValueVO)
					skuAttr.SpuSkuAttrValueId = v.SpuSkuAttrId
					skuAttr.AttrId = v.AttrId
					skuAttr.AttrName = v.AttrName
					skuAttr.AttrValueId = v.AttrValueId
					skuAttr.AttrValueName = v.AttrValueName
					spuSkuAttrArr = append(spuSkuAttrArr, skuAttr)
				}
			}
			vo.Stock = int32(v.Stock)
			vo.TotalStock = int32(v.ActualStock)
			vo.SpuSkuAttrValues = spuSkuAttrArr
			// 统计总的库存
			spuStock = spuStock + vo.Stock
			spuActualStock = spuActualStock + vo.TotalStock
			skuInfoArr = append(skuInfoArr, &vo)
		}
		resp.SkuArr = skuInfoArr
		resp.SpuAttrArr = attrValueVoArr
		resp.ActualStock = int64(spuActualStock)
		resp.TotalStock = int64(spuStock)
	}
	return resp
}

func (l *QuerySpuInfoLogic) querySkuAttr(in *pb.QuerySpuInfoDTO, err error) (map[int64][]entity.SpuSkuAttrValueEntity, error) {
	attrValueMapper := mapper.NewSpuSkuAttrValueMapper()
	spuSkuAttrValueBO := bo.SpuSkuAttrValueBO{SpuId: in.SpuId}
	skuAttrArr, err := attrValueMapper.SelectListCtx(l.ctx, l.svcCtx.DBEngin, spuSkuAttrValueBO)
	if err != nil {
		return nil, err
	}
	spuSkuAttrValueMap := make(map[int64][]entity.SpuSkuAttrValueEntity)
	for _, v := range skuAttrArr {
		skuAttrValueBOList := spuSkuAttrValueMap[v.SkuId]
		if skuAttrValueBOList == nil {
			skuAttrValueBOList = make([]entity.SpuSkuAttrValueEntity, 0)
		}
		skuAttrValueBOList = append(skuAttrValueBOList, v)
		spuSkuAttrValueMap[v.SkuId] = skuAttrValueBOList
	}
	fmt.Println(tools.BeanToJson(spuSkuAttrValueMap))
	return spuSkuAttrValueMap, nil
}

func (l *QuerySpuInfoLogic) querySpuAttr(in *pb.QuerySpuInfoDTO, err error) ([]*pb.SpuAttrValueVO, error) {
	valueMapper := mapper.NewSpuAttrValueMapper()
	valueBO := bo.SpuAttrValueBO{SpuId: in.SpuId}
	attrValueArr, err := valueMapper.SelectListCtx(l.ctx, l.svcCtx.DBEngin, valueBO)
	if err != nil {
		return nil, err
	}
	var attrValueVoArr []*pb.SpuAttrValueVO
	if len(attrValueArr) > 0 {
		for _, v := range attrValueArr {
			vo := pb.SpuAttrValueVO{}
			vo.SpuAttrValueId = v.SpuAttrValueId
			vo.AttrId = v.AttrId
			vo.AttrValueId = v.SpuAttrValueId
			vo.AttrName = v.AttrName
			vo.AttrValueName = v.AttrValueName
			attrValueVoArr = append(attrValueVoArr, &vo)
		}
	}
	return attrValueVoArr, nil
}
